package allen.util;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import allen.log.Log;
import allen.log.LogFactory;

import com.wutka.jox.JOXBeanInputStream;
import com.wutka.jox.JOXBeanOutputStream;

public class FileUtil {

	private static Log log = LogFactory.getLog(FileUtil.class);

	private static void createNewFile(File file) {
		if (!file.exists()) {
			try {
				file.createNewFile();
			} catch (IOException e) {
				log.err("create file fail.", e);
				throw new RuntimeException(e);
			}
		}
	}

	/**
	 * Save object to file.
	 * */
	public static void saveObject(Object obj, String fileName) {
		saveObject(obj, new File(fileName));
	}

	/**
	 * Save object to file.
	 * */
	public static void saveObject(Object obj, File file) {
		createNewFile(file);
		ObjectOutputStream oos = null;
		try {
			oos = new ObjectOutputStream(new BufferedOutputStream(
					new FileOutputStream(file)));
			oos.writeObject(obj);
			oos.flush();
		} catch (Exception ex) {
			log.err(ex);
			throw new RuntimeException(ex);
		} finally {
			if (oos != null) {
				try {
					oos.close();
				} catch (IOException e) {
					log.warn(e);
				}
			}
		}
	}

	/**
	 * Load object from file.
	 * */
	public static <T> T loadObject(Class<T> c, String fileName) {
		return loadObject(c, new File(fileName));
	}

	/**
	 * Load object from file.
	 * */
	public static <T> T loadObject(Class<T> c, File file) {
		checkFileExistence(file);
		T result = null;
		ObjectInputStream ois = null;
		try {
			ois = new ObjectInputStream(new FileInputStream(file));
			Object obj = ois.readObject();
			result = c.cast(obj);
		} catch (Exception ex) {
			log.err(ex);
			throw new RuntimeException(ex);
		} finally {
			if (ois != null) {
				try {
					ois.close();
				} catch (IOException e) {
					log.warn(e);
				}
			}
		}
		return result;
	}

	/**
	 * Save object to the file.
	 * */
	public static void saveObjectUsingXml(Object obj, String fileName) {
		saveObjectUsingXml(obj, new File(fileName));
	}

	/**
	 * Save object to the file.
	 * */
	public static void saveObjectUsingXml(Object obj, File f) {
		createNewFile(f);

		FileOutputStream fileOut = null;
		JOXBeanOutputStream joxOut = null;
		try {
			fileOut = new FileOutputStream(f);
			joxOut = new JOXBeanOutputStream(fileOut);
			joxOut.writeObject("Allen", obj);
			joxOut.flush();
		} catch (Exception ex) {
			log.err(ex);
			throw new RuntimeException(ex);
		} finally {
			if (joxOut != null) {
				try {
					joxOut.close();
				} catch (IOException e) {
					log.warn(e);
				}
			}
		}
	}

	/**
	 * Load object from file.
	 * */
	public static <T> T loadObjectFromXml(Class<T> c, String fileName) {
		return loadObjectFromXml(c, new File(fileName));
	}

	/**
	 * Load object from file.
	 * */
	public static <T> T loadObjectFromXml(Class<T> c, File f) {
		checkFileExistence(f);
		T result = null;
		FileInputStream fileIn = null;
		JOXBeanInputStream joxIn = null;
		try {
			fileIn = new FileInputStream(f);
			joxIn = new JOXBeanInputStream(fileIn);
			result = c.cast(joxIn.readObject(c));
		} catch (Exception ex) {
			log.err(ex);
			throw new RuntimeException(ex);
		} finally {
			if (joxIn != null) {
				try {
					joxIn.close();
				} catch (IOException e) {
					log.warn(e);
				}
			}
		}
		return result;
	}

	/**
	 * Check file is dir.
	 * */
	public static void checkIsDir(File file) {
		checkFileExistence(file);
		if (file.isFile()) {
			log.err("File is not dir. File name = " + file.getAbsolutePath());
			throw new RuntimeException(file.getAbsolutePath());
		}
	}

	/**
	 * Check file is file.
	 * */
	public static void checkIsFile(File file) {
		checkFileExistence(file);
		if (file.isDirectory()) {
			log.err("File is not file. File name = " + file.getAbsolutePath());
			throw new RuntimeException(file.getAbsolutePath());
		}
	}

	/**
	 * Check whether the file exist?
	 * */
	public static void checkFileExistence(File file) {
		if (file == null) {
			log.err("Null pointer of file.");
			throw new RuntimeException();
		}
		if (!file.exists()) {
			log.err("File is not exist. File name = " + file.getAbsolutePath());
			throw new RuntimeException(file.getAbsolutePath());
		}
	}

	/**
	 * Get the last name or drive name of path.
	 * */
	public static String getLastNameOrDriveName(String path) {
		File file = new File(path);
		FileUtil.checkIsDir(file);
		String lastName = file.getName();
		// get drive name.
		if (lastName.equals("")) {
			lastName += path.charAt(0);
		}
		return lastName;
	}

	/**
	 * Delete a file.
	 * */
	public static void deleteFile(String fileName) {
		if (StringUtil.isEmptyString(fileName))
			return;
		File file = new File(fileName);
		if (file.exists() && file.isFile())
			file.delete();
	}

}
